package com.benmei.weike.service;

import com.benmei.weike.config.SmallProgramParameter;
import com.benmei.weike.dao.TdNtMemberDao;
import com.benmei.weike.dao.TsNtSendHisDao;
import com.benmei.weike.dto.wechatSmallProgram.CheckoutUserState;
import com.benmei.weike.dto.wechatSmallProgram.GetOpenIdResponse;
import com.benmei.weike.dto.wechatSmallProgram.RegisterSmallProgramDto;
import com.benmei.weike.entity.MemberResister;
import com.benmei.weike.entity.TsNtSendHis;
import com.benmei.weike.exception.ClientException;
import com.benmei.weike.exception.ServerException;
import com.benmei.weike.util.*;
import com.nativetalk.base.RetInfo;
import com.nativetalk.bean.member.TdNtMember;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.beans.Transient;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created by waijiaojun on 2017/11/2.
 */
@Service
public class WechatSmallProgramService {
    //获取用户openID接口
    public static final String smallProgramLoginUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";

    @Resource
    private SmallProgramParameter smallProgramParameter;
    @Resource
    private TdNtMemberDao tdNtMemberDao;
    @Resource
    private WechatSmallProgramService wechatSmallProgramService;
    @Resource
    private TsNtSendHisDao tsNtSendHisDao;

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMM");

    private static Logger logger = LoggerFactory.getLogger(WechatSmallProgramService.class);

    /**
     * 获取用户openID
     *
     * @param code
     * @return
     * @throws IOException
     */
    public GetOpenIdResponse getOpenId(String code) throws IOException {
        String url = smallProgramLoginUrl.replace("APPID", smallProgramParameter.getAppId()).replace("SECRET", smallProgramParameter.getSecret()).replace("JSCODE", code).trim();
        String response = HttpUtil.getRequest(url);
        GetOpenIdResponse content = JsonUtilInWechat.fromJson(response, GetOpenIdResponse.class);
        return content;
    }

    /**
     * 获取用户openID
     *
     * @param code
     * @return OpenId
     * @throws IOException
     */
    public String getRealOpenId(String code) throws IOException {
        String url = smallProgramLoginUrl.replace("APPID", smallProgramParameter.getAppId()).replace("SECRET", smallProgramParameter.getSecret()).replace("JSCODE", code).trim();
        String response = HttpUtil.getRequest(url);
        GetOpenIdResponse content = JsonUtilInWechat.fromJson(response, GetOpenIdResponse.class);
        if (StringUtils.isNotBlank(content.getErrcode())) {
            throw new ServerException(content.getErrcode(), content.getErrmsg());
        }
        return content.getOpenid();
    }


    /**
     * 获取用户token
     *
     * @param jsCode
     * @return
     * @throws IOException
     */
    public Map<String, String> getToken(String jsCode) throws IOException {
        String tonken = "";
        Map<String, String> map = new HashedMap();
        GetOpenIdResponse getOpenIdResponse = wechatSmallProgramService.getOpenId(jsCode);
        TdNtMember tdNtMember = new TdNtMember();
        if (StringUtils.isNotBlank(getOpenIdResponse.getOpenid())) {
            tdNtMember = tdNtMemberDao.findTdNtMemberByOpenId(getOpenIdResponse.getOpenid());
        }
        if (StringUtils.isNotBlank(getOpenIdResponse.getErrcode())) {
            throw new ClientException(getOpenIdResponse.getErrcode(), getOpenIdResponse.getErrmsg());
        }
        if (tdNtMember != null) {
            map.put("exist", "1");
            map.put("desc", "该用户已存在");
            map.put("token", tdNtMember.getToken());
            map.put("phone", tdNtMember.getMemb_phone());
        } else {
            map.put("exist", "0");
            map.put("openId", getOpenIdResponse.getOpenid());
            map.put("desc", "该用户不存在");
        }
        return map;
    }

    public Map<String, String> getNewMemberToken(RegisterSmallProgramDto registerSmallProgramDto) throws IOException {
        Map<String, String> map = new HashedMap();
        /**
         * 判断用户是否已存在
         */
        TdNtMember tdNtMember = tdNtMemberDao.findTdNtMemberRegisterSms(registerSmallProgramDto.getMemberPhone());
        if (tdNtMember != null) {
            map.put("message", "该手机号已被注册");
            return map;
        }
        /**
         * 新用户注册
         */
        MemberResister memberResister = new MemberResister();
        memberResister.setMemb_phone_area(registerSmallProgramDto.getMemberPhoneArea());
        memberResister.setMemb_phone(registerSmallProgramDto.getMemberPhone());
        memberResister.setMemb_password(MD5Util.code(registerSmallProgramDto.getMemberPassword()));
        memberResister.setMemb_head_portrait(registerSmallProgramDto.getMemberHeadPortrait());
        memberResister.setMemb_sex(registerSmallProgramDto.getSex());
        memberResister.setMemb_name(registerSmallProgramDto.getMemberName());
        GetOpenIdResponse getOpenIdResponse = wechatSmallProgramService.getOpenId(registerSmallProgramDto.getCode());
        if (StringUtils.isNotBlank(getOpenIdResponse.getErrcode())) {
            throw new ClientException(getOpenIdResponse.getErrcode(), getOpenIdResponse.getErrmsg());
        }
        if (StringUtils.isNotBlank(getOpenIdResponse.getOpenid())) {
            memberResister.setSmall_program_open_id(getOpenIdResponse.getOpenid());
        }
        memberResister.setToken(String.valueOf(UUID.randomUUID()));
        memberResister.setMemb_islock("1");
        memberResister.setMemb_register_month(simpleDateFormat.format(new Date()));
        memberResister.setMemb_balance(new BigDecimal("0"));
        tdNtMemberDao.insertTdNtMember(memberResister);
        map.put("token", memberResister.getToken());
        return map;
    }

    @Transactional
    public RetInfo sendMessage(Sms sms) {
        String logInfo = this.getClass().getName() + ":smsSendMessage:";
        logger.info("=================" + logInfo + "====================");

        RetInfo retInfo = RetInfo.getSuccessInfo();

        try {
            String content = "您的验证码为CODE（5分钟内有效，如非本人操作请忽略）";
            int code = Integer.parseInt(SmsCodeUtil.getSmsCode());
            content = content.replace("CODE", code + "");
            logger.info(content);

            Integer count = tsNtSendHisDao.codeCountByPhone(sms.getMemb_phone());


            //今天是否发送过短信，如果发送过短信就校验是否超过20条
            if (count > 20) {
                retInfo.setMark(RetInfo.ReturnCode.CLIENT_ERROR);
                retInfo.setTip("发送短信超过20条");
                retInfo.setObj(sms.getMemb_phone());
                logger.info("发送短信超过20条" + sms.getMemb_phone());
                return retInfo;
            }

            //检查60秒是否发送过短信
            Timestamp now = new Timestamp(System.currentTimeMillis());
            TsNtSendHis tsh = tsNtSendHisDao.lastCodeByPhone(sms.getMemb_phone());
            if (tsh != null) {
                Timestamp time = tsh.getSend_time();
                logger.info("now=" + now + ", lastTime=" + time + ",result = " + (now.getTime() - time.getTime()) / 1000 + "秒");
                if ((now.getTime() - time.getTime()) < 50 * 1000) {
                    retInfo.setMark(RetInfo.ReturnCode.CLIENT_ERROR);
                    retInfo.setTip("60秒内发送过短信，过于频繁");
                    retInfo.setObj(sms.getMemb_phone());
                    logger.info("60秒内发送过短信，过于频繁" + sms.getMemb_phone());
                    return retInfo;
                }
            }

            //在数据库中插入该记录
            TsNtSendHis tsNtSendHis = new TsNtSendHis();
            tsNtSendHis.setPhoneno(sms.getMemb_phone());
            tsNtSendHis.setSms_provider_id(code);
            tsNtSendHis.setYyyymmdd(CommonUtil.getMonth(now));
            tsNtSendHis.setSms_type("Y");
            tsNtSendHis.setSend_time(now);
            tsNtSendHisDao.insertCode(tsNtSendHis);

            //发送短信
            boolean flag = SMSUtil.sendSms(sms, content);

            retInfo.setMark(RetInfo.ReturnCode.SUCCESS);
            retInfo.setTip("短信发送成功");
            retInfo.setObj(sms);
            return retInfo;
        } catch (Exception e) {
            retInfo.setMark(RetInfo.ReturnCode.CLIENT_ERROR);
            retInfo.setTip("系统错误");
            logger.error(e.getMessage(), e);
            return retInfo;
        }
    }

    @Transactional
    public RetInfo checkoutUser(CheckoutUserState checkoutUserState) throws IOException {
        String logInfo = this.getClass().getName() + ":checkoutUser:";
        logger.info("================" + logInfo + "=========================");

        RetInfo retInfo = new RetInfo();
        TsNtSendHis tsh = tsNtSendHisDao.lastCodeByPhone(checkoutUserState.getMemb_phone());
        Integer code = Integer.parseInt(checkoutUserState.getCode());
        if (tsh == null) {
            retInfo.setMark("-2");
            retInfo.setTip("请先获取验证码");
            return retInfo;
        }
        if (tsh.getSms_provider_id().equals(code)) {
            TdNtMember tdNtMember = tdNtMemberDao.findTdNtMemberRegisterSms(checkoutUserState.getMemb_phone());
            retInfo.setMark("1");
            Map map = new HashMap();
            if (tdNtMember != null) {
                String open_id = wechatSmallProgramService.getRealOpenId(checkoutUserState.getJs_code());
                tdNtMemberDao.updateOpenId(open_id, tdNtMember.getMemb_id());
                map.put("memb_id", tdNtMember.getMemb_id());
                map.put("token", tdNtMember.getToken());
                map.put("memb_phone", checkoutUserState.getMemb_phone());
                retInfo.setTip("绑定成功");
                retInfo.setObj(map);
                return retInfo;
            } else {
                map.put("memb_phone", checkoutUserState.getMemb_phone());
                retInfo.setTip("查询成功");
                retInfo.setObj(map);
                return retInfo;
            }
        } else {
            retInfo.setMark("-1");
            retInfo.setTip("验证码错误");
            return retInfo;
        }
    }
}
